package handlers

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"werewolf/core"

	"github.com/go-sql-driver/mysql"
)

func PlayHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
		return
	}

	room := r.URL.Query().Get("room")
	handle, err := core.Connection()
	if err != nil {
		http.Error(w, "Connection failed: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer handle.Close()

	if start := r.URL.Query().Get("start"); start != "" {          //   开始游戏

		var currentCount,targetCount int
		err = handle.QueryRow("SELECT count(*) FROM player WHERE RmNo = ?", room).Scan(&currentCount)
		if err != nil {
			http.Error(w, "cannot select count: "+err.Error(), http.StatusInternalServerError)
			return
		}

		err = handle.QueryRow("SELECT PlayerNo FROM game WHERE RmNo = ?", room).Scan(&targetCount)
		if err != nil {
			http.Error(w, "cannot select target count: "+err.Error(), http.StatusInternalServerError)
			return
		}

		if currentCount < targetCount {
			fmt.Fprintln(w, "not enough")
			return
		}

		result, err1 := handle.Exec("UPDATE Running SET `start`=1,`speaking`=0, `voting` = 0,`death1`=0,`death2`=0,`death3`=0 WHERE RmNo=?", room)
		
		rowsAffected, err2 := result.RowsAffected()
		if err1 != nil || err2 != nil || rowsAffected == 0 {
			fmt.Fprintln(w, "error" + err1.Error() + err2.Error())
		} else {
			fmt.Fprintln(w, "success")
		}

	} else if verify := r.URL.Query().Get("verify"); verify != "" {                 //   查看角色的行动状态

		role := r.URL.Query().Get("role")
		if role == "" {
			role = "start"
		}
		var prepared sql.NullString
		queryString := fmt.Sprintf("SELECT `%s` FROM Running WHERE RmNo=%s", role, room)
		err = handle.QueryRow(queryString).Scan(&prepared)
		if err != nil {
			if e, ok := err.(*mysql.MySQLError); err == sql.ErrNoRows || ok && e.Number == 1054 {
				fmt.Fprintln(w, "0")
			} else {
				http.Error(w, "play verify error "+err.Error(), http.StatusInternalServerError)
			}
		} else {
			if prepared.Valid {
				fmt.Fprintln(w, prepared.String)
			} else {
				fmt.Fprintln(w, "0")
			}
		}

	} else if acquire3 := r.URL.Query().Get("acquire3"); acquire3 != "" {            //   从数据库获得三个字段的数据
		item := r.URL.Query().Get("item")
		item2 := r.URL.Query().Get("item2")
		item3 := r.URL.Query().Get("item3")

		var p1 sql.NullString
		var p2 sql.NullString
		var p3 sql.NullString
		queryString := fmt.Sprintf("SELECT `%s`,`%s`,`%s` FROM Running WHERE RmNo= %s", item,item2,item3,room)
		err := handle.QueryRow(queryString).Scan(&p1, &p2, &p3) // 应该定义为多个变量
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		} else {
			prepared := p1.String + " " + p2.String + " " + p3.String
			fmt.Fprintln(w, prepared)
		}

	} else if acquire1 := r.URL.Query().Get("acquire1"); acquire1 != "" {
		item := r.URL.Query().Get("item")

		var p1 sql.NullString

		queryString := fmt.Sprintf("SELECT `%s` FROM Running WHERE RmNo= %s", item,room)
		err := handle.QueryRow(queryString).Scan(&p1) // 应该定义为多个变量
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		} else {
			prepared := p1.String
			fmt.Fprintln(w, prepared)
		}
		
	}else if ongoing := r.URL.Query().Get("ongoing"); ongoing != "" {            //   查看游戏是否正在进行（貌似没用）
		rows, err := handle.Query("SELECT * FROM Running WHERE RmNo=?", room)
		if err != nil {
			http.Error(w, "error", http.StatusInternalServerError)
			return
		}
		defer rows.Close()

		var prepared []map[string]interface{}
		for rows.Next() {
			var rowData = make(map[string]interface{})
			columns, _ := rows.Columns()
			values := make([]interface{}, len(columns))
			for i := range values {
				values[i] = new(sql.RawBytes)
			}
			err = rows.Scan(values...)
			if err != nil {
				http.Error(w, "error", http.StatusInternalServerError)
				return
			}
			for i, col := range columns {
				b := values[i].(*sql.RawBytes)
				rowData[col] = string(*b)
			}
			prepared = append(prepared, rowData)
		}
		json.NewEncoder(w).Encode(prepared)

	} else if vote := r.URL.Query().Get("vote"); vote != "" {            //   进行投票

		var ableVote int
		err = handle.QueryRow("SELECT voting FROM running WHERE RmNo = ? ", room).Scan(&ableVote)
		if err != nil {
			http.Error(w, "error", http.StatusInternalServerError)
			return
		}

		if ableVote == 0 {
			fmt.Fprintln(w, "not able to vote")
			return
		}

		target := r.URL.Query().Get("target")
		if target == "" {
			fmt.Fprintln(w, "allow to vote")
			return
		}
		
		user := r.URL.Query().Get("user")
		_, err := handle.Exec("UPDATE player SET Vote = ? WHERE RmNo = ? AND Username = ?",target,  room, user)
		if err != nil {
			http.Error(w, "error", http.StatusInternalServerError)
			return
		}
		fmt.Fprintln(w, "success")

	} else if sur := r.URL.Query().Get("survival"); sur != "" {               //   查看角色的生存状态
		
		role := r.URL.Query().Get("role")

		var survival int

		err = handle.QueryRow("SELECT Survival FROM player WHERE RmNo = ? and Role = ?", room, role).Scan(&survival)
		if err != nil {
			http.Error(w, "error" + err.Error(), http.StatusInternalServerError)
			return
		}

		if survival == 1 {
			fmt.Fprintln(w, "survival")
		}

	} else if update := r.URL.Query().Get("update"); update != "" {          //   更新各玩家游戏状态

		var response struct{
			Playlist map[int]string `json:"playlist"`
			Death map[int]bool `json:"death"`
			WolfList map[int]bool `json:"wolflist"`
			Role int `json:"role"`
		}

		var playNo int
		err = handle.QueryRow("SELECT PlayerNo FROM game WHERE RmNo = ?", room).Scan(&playNo)
		if err != nil {
			http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
			return
		}

		response.Death = make(map[int]bool, playNo)

		rows, err := handle.Query("SELECT No FROM Player WHERE RmNo=? and Survival=0", room)
		if err != nil {
			http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
			return 
		}

		defer rows.Close()

		for rows.Next() {
			var no int
			err = rows.Scan(&no)
			if err != nil {
				http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
				return
			}
			response.Death[int(no)] = true
		}

		rows, err = handle.Query("SELECT Username, No FROM Player WHERE RmNo=?", room)
		if err != nil {
			http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
		}

		defer rows.Close()

		response.Playlist = make(map[int]string)

		for rows.Next() {
			var (
				username string
				no int
			)
			err = rows.Scan(&username, &no)
			if err != nil {
				http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
				return
			}
			response.Playlist[int(no)] = username
		}

		response.WolfList = make(map[int]bool, playNo)
		
		//给狼人玩家返回队友列表
		Prepared, err := handle.Prepare("SELECT Role FROM Player WHERE RmNo = ? AND No = ?")
		if err != nil {
			http.Error(w, "Error preparing statement: "+err.Error(), http.StatusInternalServerError)
			return
		}

		var role int

		var rolelist []string
		JSONdata := r.URL.Query().Get("roleList")
		err = json.Unmarshal([]byte(JSONdata), &rolelist)

		if err != nil {
			http.Error(w, "Error unmarshalling roleList: "+err.Error(), http.StatusInternalServerError)
			return 
		}

		for i := 1; i <= playNo; i++ {
			err = Prepared.QueryRow(room, i).Scan(&role)
			if err == sql.ErrNoRows {
				continue
			}
			if err != nil {
				http.Error(w, "Error scanning role: "+err.Error(), http.StatusInternalServerError)
				return
			}
			if rolelist[role-1][0] == 'w' {
				response.WolfList[i] = true
			}
		}

		//实时返回玩家角色编号
		user := r.URL.Query().Get("user")
		
		err = handle.QueryRow("SELECT role FROM player WHERE RmNo = ? AND username = ?", room, user).Scan(&response.Role)
		if err != nil {
			http.Error(w, "Error scanning role: "+err.Error(), http.StatusInternalServerError)
			return
		}	

		json.NewEncoder(w).Encode(response)

	} else if end := r.URL.Query().Get("end"); end != "" {//                 自爆功能结束

		_, err := handle.Exec("UPDATE running SET `boomable`=0 WHERE RmNo=?", room)
		if err != nil {
			http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
			return
		}

		fmt.Fprintln(w, "success")

	}else if boom := r.URL.Query().Get("boom"); boom != "" {               //   查询当前时段是否能自爆

		var boomable int

		err = handle.QueryRow("SELECT Boomable From running WHERE RmNo = ?", room).Scan(&boomable)

		if err != nil {
			http.Error(w, "error"+ err.Error(), http.StatusInternalServerError)
		}

		if boomable == 1 {
			fmt.Fprintln(w, "able to boom")
		} else {
			fmt.Fprintln(w, "not able to boom")
		}

	}else {
		http.Error(w, "Invalid request", http.StatusBadRequest)
	}
}
